/*
* Copyright 2010 Dovado FZ-LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "DovadoEnableAPI.h"
#import "DovadoAppDelegate.h"
#import "DovadoURLConnection.h"
#import "DovadoEnableAPIListener.h"


@implementation DovadoEnableAPI
@synthesize receivedData;
@synthesize umrsession;

enum request_type {
	REQ_LOGIN,
	REQ_GET_FWVER,
	REQ_ENABLE_API,
} request_type_t;

NSInteger mCurrentRequestType;

-(id) initWithListener: (id<DovadoEnableAPIListener>) listener {
	mListener = listener;
	return self;
}

-(NSInteger)getFirmwareRevision:(NSString *)data {
	NSArray *lines = [data componentsSeparatedByString:@"\n"];
	NSString *regex = @".*<tr><td><b>Firmware Revision:</b></td><td>(.*)</td></tr>.*";		
	NSPredicate *regexPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
	for(NSString *line in lines)
	{
		if([regexPredicate evaluateWithObject:line]) {
			NSString *str = [[[[line componentsSeparatedByString:@"<td>"] lastObject] componentsSeparatedByString:@"</td>"] objectAtIndex:0];
			if([str length] >= 5) {
				return [[[str substringToIndex:5] stringByReplacingOccurrencesOfString:@"." withString:@""] intValue];
			}
		}
	}
	
	return 0;
}

- (void) sendRequest {
	NSLog(@"sendRequest");
	DovadoAppDelegate *appDelegate = (DovadoAppDelegate*)[[UIApplication sharedApplication] delegate];
	NSMutableURLRequest *request;
	NSString *host;
	if(![appDelegate.mHostAddress hasPrefix:@"http://"]) {
		host =[NSString stringWithFormat:@"http://%@", appDelegate.mHostAddress];
	} else {
		host = appDelegate.mHostAddress;
	}
	NSString *user = appDelegate.mUser;
	NSString *password = appDelegate.mPassword;
	
	switch (mCurrentRequestType) {
		case REQ_LOGIN:
			NSLog(@"REQ_LOGIN");
			request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/cgi-bin/login.cgi", host]]
											cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
			NSString *postString = [NSString stringWithFormat:@"LOGINUNAME=%@&LOGINPASSWD=%@", user, password];
			[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
			[request setValue:[NSString stringWithFormat:@"%d", [postString length]] forHTTPHeaderField:@"Content-Length"];
			[request setValue: @"" forHTTPHeaderField:@"Cookie"];
			[request setHTTPMethod:@"POST"];
			[request setHTTPBody: [postString dataUsingEncoding:NSUTF8StringEncoding]];
			break;
		case REQ_GET_FWVER:
			NSLog(@"REQ_GET_FWVER");
			request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/cgi-bin/getcfg.cgi?home", host]]
											cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
			[request setValue:@"html/text" forHTTPHeaderField:@"Content-Type"];
			[request setValue:@"0" forHTTPHeaderField:@"Content-Length"];
			[request setValue: [NSString stringWithFormat:@"%@=%@", [umrsession name], [umrsession value]] forHTTPHeaderField:@"Cookie"];
			[request setHTTPMethod:@"GET"];
			break;
		case REQ_ENABLE_API:
			NSLog(@"REQ_ENABLE_API");
			request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/cgi-bin/getcfg.cgi?extcmd+enablelanapi", host]]
											cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
			[request setValue:@"html/text" forHTTPHeaderField:@"Content-Type"];
			[request setValue:@"0" forHTTPHeaderField:@"Content-Length"];
			[request setValue: [NSString stringWithFormat:@"%@=%@", [umrsession name], [umrsession value]] forHTTPHeaderField:@"Cookie"];
			[request setHTTPMethod:@"GET"];
			break;
	}
	
	DovadoURLConnection *connection = [[DovadoURLConnection alloc] initWithRequest:request delegate:self];
	if(connection) {
		NSLog(@"Success!!!");
		receivedData = [[NSMutableData data] retain];
	} else {
		NSLog(@"Failed!");
		[mListener dovadoEnableAPICallback:STATUS_FAILED];
	}
}


-(void) enableAPI {
	NSLog(@"enableAPI");
	mCurrentRequestType = REQ_LOGIN;
	[self sendRequest];
}

#pragma mark DovadoURLConnection delegate methods
- (NSURLRequest *)connection:(DovadoURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse {
	NSLog(@"willSendRequest");
	
	if(redirectResponse){
		NSDictionary *headerFields = [(NSHTTPURLResponse*)redirectResponse allHeaderFields];   
		NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headerFields forURL:[NSURL URLWithString:@"http://192.168.0.1/cgi-bin/login.cgi"]];
		for(NSHTTPCookie *cookie in cookies) {
			if ([[cookie name] isEqualToString: @"umrsession"]) {
				umrsession = [[NSHTTPCookie alloc] initWithProperties:[cookie properties]];
			}
		}
	}
	NSLog(@"request sent off");
	return request;
}

- (void)connection:(DovadoURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
	NSLog(@"didReceiveResponse");
	// This method is called when the server has determined that it
	// has enough information to create the NSURLResponse.
	
	// It can be called multiple times, for example in the case of a
	// redirect, so each time we reset the data.
	
	[receivedData setLength:0];
	
}

- (void)connection:(DovadoURLConnection *)connection didReceiveData:(NSData *)data {
	NSLog(@"didReceiveData");
	/* Append the new data to receivedData. */
	[receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	NSLog(@"didFailWithError");
	/* release the connection, and the data object */
	[connection release];
	[receivedData release];
	
	NSLog(@"Connection failed! Error - %@ %@",
		  [error localizedDescription],
		  [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
	
	if([[error domain] isEqual:DOVADO_URL_CONNECTION_ERROR_DOMAIN] && [error code] == kDovadoURLConnectionTimedOut){
		[mListener dovadoEnableAPICallback:STATUS_TIMEOUT];
	} else {
		[mListener dovadoEnableAPICallback:STATUS_FAILED];
	}
}


- (void)connectionDidFinishLoading:(DovadoURLConnection *)connection {
	NSLog(@"connectionDidFinishLoading");
	NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
	
	[connection release];
	switch (mCurrentRequestType) {
		case REQ_LOGIN:
			[receivedData release];
			mCurrentRequestType = REQ_GET_FWVER;
			[self sendRequest];
			break;
		case REQ_GET_FWVER:
			NSLog(@"Got firmware version");
			NSInteger version = [self getFirmwareRevision:[[NSString alloc]initWithData:receivedData encoding:NSUTF8StringEncoding]];
			[receivedData release];
			NSLog(@"Version: %d", version);
			if(version == 0) {
				NSLog(@"Did not find a valid firmware version");
				[mListener dovadoEnableAPICallback:STATUS_FAILED];
			} else if(version < 430){
				NSLog(@"Firmware is too old, UPDATE it sucker!");
				[mListener dovadoEnableAPICallback:STATUS_OLD_FIRMWARE];
			} else {
				NSLog(@"Firmware is valid so proced with enabling the API");
				/* The firmware is a valid firmware, so we can proceed */
				mCurrentRequestType = REQ_ENABLE_API;
				[self sendRequest];
			}
			break;
		case REQ_ENABLE_API:
			NSLog(@"Woohoooo we did it, we finished!!");
			[receivedData release];
			[mListener dovadoEnableAPICallback:STATUS_OK];
			break;
	}
}


- (void)dealloc {
	[super dealloc];
}

@end
